package cn.bugstack.mybatis.builder.xml;

import cn.bugstack.mybatis.builder.BaseBuilder;
import cn.bugstack.mybatis.datasource.DataSourceFactory;
import cn.bugstack.mybatis.datasource.druid.DruidDatasourceFactory;
import cn.bugstack.mybatis.io.Resources;
import cn.bugstack.mybatis.mapping.*;
import cn.bugstack.mybatis.scripting.LanguageDriver;
import cn.bugstack.mybatis.scripting.LanguageDriverRegistry;
import cn.bugstack.mybatis.scripting.defaults.RawSqlSource;
import cn.bugstack.mybatis.scripting.defaults.StaticSqlSource;
import cn.bugstack.mybatis.scripting.xmltags.XMLLanguageDriver;
import cn.bugstack.mybatis.session.Configuration;
import cn.bugstack.mybatis.transaction.TransactionFactory;
import cn.bugstack.mybatis.type.JdbcType;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import org.xml.sax.InputSource;

import javax.sql.DataSource;
import java.io.IOException;
import java.io.Reader;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class XmlConfigBuilder extends BaseBuilder {

    private Element root;

    public XmlConfigBuilder(Reader reader) {
        super(new Configuration());
        // dom4j parse xml
        SAXReader saxReader = new SAXReader();
        try {
            Document document = saxReader.read(new InputSource(reader));
            root = document.getRootElement();
        } catch (DocumentException e) {
            throw new RuntimeException(e);
        }

    }

    public Configuration parse() throws Exception {


        environmentElement(root.element("environments"));
        mapperElement(root.element("mappers"));
        return configuration;
    }

    private void environmentElement(Element environments) throws Exception{
        String defaultEnv = environments.attributeValue("default");
        List<Element> environmentList = environments.elements("environment");
        for (Element environment : environmentList) {
            String id = environment.attributeValue("id");
            if (id.equals(defaultEnv)) {
                Element transactionManager = environment.element("transactionManager");
                String transactionManagerType = transactionManager.attributeValue("type");
                TransactionFactory transactionFactory = (TransactionFactory) typeAliasRegistry.resolveAlias(transactionManagerType).newInstance();


                Element dataSourceElement = environment.element("dataSource");
                String type = dataSourceElement.attributeValue("type");
                DataSourceFactory dataSourceFactory = (DataSourceFactory) typeAliasRegistry.resolveAlias(type).newInstance();
                Properties properties = new Properties();
                for (Element property : dataSourceElement.elements("property")) {
                    String name = property.attributeValue("name");
                    String value = property.attributeValue("value");
                    properties.put(name, value);
                }
                dataSourceFactory.setProperties(properties);
                DataSource dataSource = dataSourceFactory.getDataSource();
                Environment.Builder environmentBuilder = new Environment.Builder(id).transactionFactory(transactionFactory).dataSource(dataSource);
                configuration.setEnvironment(environmentBuilder.build());
            }
        }
    }

    private void mapperElement(Element mappers) throws Exception {
        List<Element> mapperList = mappers.elements("mapper");
        for (Element mapper : mapperList) {
            XmlMapperBuilder xmlMapperBuilder = new XmlMapperBuilder(configuration, mapper,mapper.attributeValue("resource"));
            xmlMapperBuilder.parse();
        }
    }

}
